import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Created by jiangzeyin on 2017/4/21.
 */
public class IpMain {

    private static final ConcurrentHashMap<String, String> ipMap = new ConcurrentHashMap<>();
    private static final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool();
    private static final File ipInfo = new File("/ip.txt");

    public static void main(String[] args) throws IOException, InterruptedException {
        start();
    }

    private static void start() throws InterruptedException {
        for (int i = 1; i <= 20; i++) {
            int finalI = i;
            executor.execute(() -> {
                try {
                    post(finalI);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        while (true) {
            int count = executor.getActiveCount();
            if (count == 0)
                break;
            Thread.sleep(200);
        }
        System.out.println("结束啦");
    }

    private static void post(int pageNo) throws IOException {
        Connection conn = Jsoup.connect(String.format("http://www.kuaidaili.com/free/inha/%d/", pageNo));
        Document doc = conn.get();
        Elements elements = doc.getElementsByTag("tr");
        elements.forEach(element -> {
            // System.out.println(element);
            Elements tds = element.getElementsByTag("td");
            Elements ips = tds.select("[data-title=\"IP\"]");
            Element ip_node = ips.first();
            if (ip_node == null) {
                return;
            }
            Elements ports = tds.select("[data-title=\"PORT\"]");
            Element port_node = ports.first();
            if (port_node == null) {
                System.out.println("异常");
                return;
            }

            Elements address_s = tds.select("[data-title=\"位置\"]");
            Element address_node = address_s.first();
            if (address_node == null) {
                System.out.println("异常");
                return;
            }
            executor.execute(() -> {
                if (isHostConnect(ip_node.text(), Integer.parseInt(port_node.text()))) {
                    String ipInfo = ip_node.text() + ":" + port_node.text();
                    String address = address_node.text();
                    ipMap.put(ipInfo, address);
                    System.out.println(ipInfo + "  " + address);
                    appendInfo(ipInfo + "-" + address);
                }
            });

        });
    }

    private static void appendInfo(String line) {
        executor.execute(() -> {
            synchronized (IpMain.class) {
                try {
                    FileWriter writer = new FileWriter(ipInfo, true);
                    BufferedWriter bw = new BufferedWriter(writer);
                    bw.write(line);
                    bw.newLine();
                    bw.close();
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private static boolean isHostConnect(String host, int port) {
        Socket socket = new Socket();
        try {
            socket.connect(new InetSocketAddress(host, port));
        } catch (IOException e) {
            return false;
        } finally {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

}
